﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Adorners;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public class MarkText : Expression
    {
        public MarkText(SubPanel rootPanel, SubPanel parentPanel, Editor editor)
            : base(rootPanel, parentPanel, editor)
        {
            StackPanel panel = new StackPanel();
            panel.Orientation = Orientation.Vertical;

            topMarkBox = new TextBox();
            topMarkBox.Foreground = ExForeground;
            topMarkBox.MouseDoubleClick +=
                new System.Windows.Input.MouseButtonEventHandler(topMarkBox_MouseDoubleClick);
            topMarkBox.MouseLeftButtonDown +=
                new System.Windows.Input.MouseButtonEventHandler(topMarkBox_MouseLeftButtonDown);
            topMarkBox.MouseRightButtonDown +=
                new System.Windows.Input.MouseButtonEventHandler(topMarkBox_MouseRightButtonDown);
            topMarkBox.MouseLeftButtonUp +=
                new System.Windows.Input.MouseButtonEventHandler(topMarkBox_MouseLeftButtonUp);

            topMarkBox.HorizontalAlignment = HorizontalAlignment.Center;

            bottomMarkBox = new TextBox();
            bottomMarkBox.Foreground = ExForeground;
            bottomMarkBox.MouseDoubleClick +=
                new System.Windows.Input.MouseButtonEventHandler(bottomMarkBox_MouseDoubleClick);
            bottomMarkBox.MouseLeftButtonDown +=
                new System.Windows.Input.MouseButtonEventHandler(bottomMarkBox_MouseLeftButtonDown);
            bottomMarkBox.MouseRightButtonDown +=
                new System.Windows.Input.MouseButtonEventHandler(bottomMarkBox_MouseRightButtonDown);
            bottomMarkBox.MouseLeftButtonUp +=
                new System.Windows.Input.MouseButtonEventHandler(bottomMarkBox_MouseLeftButtonUp);

            bottomMarkBox.Margin = midThickness;
            bottomMarkBox.HorizontalAlignment = HorizontalAlignment.Center;

            panel.Children.Add(topMarkBox); panel.Children.Add(bottomMarkBox);

            adornerDecorator = new AdornerDecorator();
            adornerDecorator.Child = panel;

            this.mainBorder.Child = adornerDecorator;

            #region 绑定字号。
            MultiBinding textFontSizeLevelBinding = new MultiBinding();
            Binding fsBinding = new Binding("ExFontSize");
            fsBinding.Source = editor;

            Binding fslBinding = new Binding("FontSizeLevel");
            fslBinding.Source = this;

            textFontSizeLevelBinding.Bindings.Add(fsBinding);
            textFontSizeLevelBinding.Bindings.Add(fslBinding);

            textFontSizeLevelBinding.Converter = Globals.markTextSizeConverter;

            BindingOperations.SetBinding(this.topMarkBox, TextBox.FontSizeProperty, textFontSizeLevelBinding);
            BindingOperations.SetBinding(this.bottomMarkBox, TextBox.FontSizeProperty, textFontSizeLevelBinding);
            #endregion

            this.chineseName = "上下标式";
        }

        private static Thickness midThickness = new Thickness(0, 3, 0, 0);

        private AdornerDecorator adornerDecorator;

        public enum AssistLine { None, SingleLine, DoubleLine, RightArrow, LeftArrow, DoubleArrow }

        private AssistLine midline = AssistLine.None;

        public AssistLine Midline
        {
            get { return midline; }
            set
            {
                midline = value;
                if (this.XmlData != null)
                {
                    this.XmlData.SetAttribute("MidLine", midline.ToString());
                }

                RefreshMidLine();
            }
        }

        private AssistAdorner midAdorner;

        private void RefreshMidLine()
        {
            switch (midline)
            {
                case AssistLine.None:
                    {
                        if (this.midAdorner != null)
                        {
                            this.midAdorner.Visibility = Visibility.Hidden;
                        }
                        break;
                    }
                default:
                    {
                        //显示
                        if (this.midAdorner == null)
                        {
                            this.midAdorner = new AssistAdorner(this);
                            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainBorder);
                            adornerLayer.Add(this.midAdorner);
                        }
                        else
                        {
                            this.midAdorner.Visibility = Visibility.Visible;
                        }

                        break;
                    }
            }

            if (this.midAdorner != null)
            {
                this.midAdorner.InvalidateVisual();
            }
        }

        void bottomMarkBox_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor == null) return;
            Editor.SelectedExpression = this;
            e.Handled = true;
        }

        void topMarkBox_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor == null) return;
            Editor.SelectedExpression = this;
            e.Handled = true;
        }

        void bottomMarkBox_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // 接收拖动来的公式。
            Globals.DropExpression(this);
        }

        void topMarkBox_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // 接收拖动来的公式。
            Globals.DropExpression(this);
        }

        void bottomMarkBox_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor == null) return;
            Editor.SelectedExpression = this;

            //准备拖动公式。
            Globals.dragSourceExpression = this;
            e.Handled = true;
        }

        void bottomMarkBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.Editor.SelectedExpression = this;
            Commands.Command.EditMarkText(this);
            e.Handled = true;
        }

        void topMarkBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.Editor.SelectedExpression = this;
            Commands.Command.EditMarkText(this);
            e.Handled = true;
        }

        void topMarkBox_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor == null) return;
            Editor.SelectedExpression = this;

            //准备拖动公式。
            Globals.dragSourceExpression = this;
            e.Handled = true;
        }

        /// <summary>
        /// 字号缩放等级。
        /// </summary>
        private int fontSizeLevel = 0;

        public int FontSizeLevel
        {
            get { return fontSizeLevel; }
            set
            {
                if (value >= 0 && value <= 6)
                {
                    fontSizeLevel = value;
                    this.XmlData.SetAttribute("FontSizeLevel", value.ToString());

                    OnPropertyChanged(this, new PropertyChangedEventArgs("FontSizeLevel"));
                }
            }
        }

        private TextBox topMarkBox;

        public TextBox TopMarkBox
        {
            get { return topMarkBox; }
        }

        public String TopMarkText
        {
            get { return this.topMarkBox.Text; }
            set
            {
                this.topMarkBox.Text = value;

                // 向后台写入xml数据。
                XmlNode textNode = this.XmlData.SelectSingleNode("TopMarkText");
                if (textNode != null)
                {
                    textNode.InnerText = value;
                }
                else
                {
                    MessageBox.Show("未找到“TopMarkText”节点，无法修改文本块内容文本！",
                        Globals.appName, MessageBoxButton.OK,
                        MessageBoxImage.Warning);
                }

                this.Editor.IsModified = true;
            }
        }

        private TextBox bottomMarkBox;

        public TextBox BottomMarkBox
        {
            get { return bottomMarkBox; }
        }

        public String BottomMarkText
        {
            get { return this.bottomMarkBox.Text; }
            set
            {
                this.bottomMarkBox.Text = value;

                // 向后台写入xml数据。
                XmlNode textNode = this.XmlData.SelectSingleNode("BottomMarkText");
                if (textNode != null)
                {
                    textNode.InnerText = value;
                }
                else
                {
                    MessageBox.Show("未找到“BottomMarkText”节点，无法修改文本块内容文本！",
                        Globals.appName, MessageBoxButton.OK,
                        MessageBoxImage.Warning);
                }

                this.Editor.IsModified = true;
            }
        }

        public override Brush ExForeground
        {
            get
            {
                return base.ExForeground;
            }
            set
            {
                UpdateExForegroundWithoutXmlChanging(value);
                UpdateExForegroundToXmlData(value);
                Editor.IsModified = true;
            }
        }

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            base.exForeground = value;
            this.topMarkBox.Foreground = value;
            this.bottomMarkBox.Foreground = value;

            if (this.midAdorner != null)
            {
                this.midAdorner.InvalidateVisual();
            }
        }

        protected override void BuildChildren()
        {
            base.BuildChildren();

            if (this.XmlData == null) return;

            if (this.topMarkBox == null)
            {
                this.topMarkBox = new TextBox();
                this.Child = this.topMarkBox;
            }

            //读取文本
            XmlNode topMarkNode = this.XmlData.SelectSingleNode("TopMarkText");
            this.topMarkBox.Text = topMarkNode.InnerText;

            XmlNode bottomMarkNode = this.XmlData.SelectSingleNode("BottomMarkText");
            this.bottomMarkBox.Text = bottomMarkNode.InnerText;

            XmlAttribute attrFontName = XmlData.GetAttribute("FontName");
            if (attrFontName != null)
            {
                this.fontName = attrFontName.Value;
                this.topMarkBox.FontFamily = new FontFamily(attrFontName.Value);
                this.bottomMarkBox.FontFamily = new FontFamily(attrFontName.Value);
            }

            XmlAttribute attrFontWeight = XmlData.GetAttribute("FontWeight");
            if (attrFontWeight != null)
            {
                this.fontWeight = GetFontWeightFromString(attrFontWeight.Value);
                this.topMarkBox.FontWeight = this.fontWeight;
                this.bottomMarkBox.FontWeight = this.fontWeight;
            }

            XmlAttribute attrFontStyle = XmlData.GetAttribute("FontStyle");
            if (attrFontStyle != null)
            {
                this.fontStyle = GetFontStyleFromString(attrFontStyle.Value);
                this.topMarkBox.FontStyle = this.fontStyle;
                this.bottomMarkBox.FontStyle = this.fontStyle;
            }

            XmlAttribute attrFontSizeLevel = XmlData.GetAttribute("FontSizeLevel");
            if (attrFontSizeLevel != null)
            {
                this.fontSizeLevel = int.Parse(attrFontSizeLevel.Value);
                OnPropertyChanged(this, new PropertyChangedEventArgs("FontSizeLevel"));
            }

            XmlAttribute attrMidLine = XmlData.GetAttribute("MidLine");
            if (attrMidLine != null && attrMidLine.Value != "None")
            {
                this.midline = (AssistLine)Enum.Parse(typeof(AssistLine), attrMidLine.Value);
                RefreshMidLine();
            }
        }

        private string fontName = Globals.SysFontFamily;

        public string FontName
        {
            get { return fontName; }
            set
            {
                if (fontName != value && value.Length > 0)
                {
                    fontName = value;
                    this.topMarkBox.FontFamily = new FontFamily(fontName);
                    this.bottomMarkBox.FontFamily = this.topMarkBox.FontFamily;
                    if (this.XmlData != null)
                    {
                        this.XmlData.SetAttribute("FontName", fontName);
                    }
                    Editor.IsModified = true;
                }
            }
        }

        private FontWeight fontWeight = FontWeights.Normal;

        public FontWeight FontWeight
        {
            get { return fontWeight; }
            set
            {
                fontWeight = value;
                if (this.XmlData != null)
                {
                    this.XmlData.SetAttribute("FontWeight", fontWeight.ToString());
                }

                this.topMarkBox.FontWeight = fontWeight;
                this.bottomMarkBox.FontWeight = fontWeight;
                Editor.IsModified = true;
            }
        }

        private FontStyle fontStyle = FontStyles.Normal;

        public FontStyle FontStyle
        {
            get { return fontStyle; }
            set
            {
                fontStyle = value;
                if (this.XmlData != null)
                {
                    this.XmlData.SetAttribute("FontStyle", fontStyle.ToString());
                }

                this.topMarkBox.FontStyle = fontStyle;
                this.bottomMarkBox.FontStyle = fontStyle;
                Editor.IsModified = true;
            }
        }

        public static FontWeight GetFontWeightFromString(string fontWeightString)
        {
            switch (fontWeightString)
            {
                case "Bold": return FontWeights.Bold;
                default: return FontWeights.Normal;// 目前只支持两种。
            }
        }

        public static FontStyle GetFontStyleFromString(string fontStyleString)
        {
            switch (fontStyleString)
            {
                case "Italic": return FontStyles.Italic;
                default: return FontStyles.Normal;// 目前只支持两种。
            }
        }

        public override void SetProperty(string propertyName, string value)
        {
            base.SetProperty(propertyName, value);

            switch (propertyName)
            {
                case "TopMarkText":
                    {
                        this.TopMarkText = value;
                        break;
                    }
                case "BottomMarkText":
                    {
                        this.BottomMarkText = value;
                        break;
                    }
                case "ExForeground":
                    {
                        Brush brush = ColorPicker.GetBrushByName(value);
                        this.ExForeground = brush;
                        break;
                    }
                case "FontStyle":
                    {
                        switch (value)
                        {
                            case "Italic":
                                {
                                    this.FontStyle = FontStyles.Italic;
                                    this.Editor.ParentWindow.tbtnItalic.IsChecked = true;
                                    break;
                                }
                            default:
                                {
                                    this.FontStyle = FontStyles.Normal;
                                    this.Editor.ParentWindow.tbtnItalic.IsChecked = false;
                                    break;
                                }
                        }
                        break;
                    }
                case "FontWeight":
                    {
                        switch (value)
                        {
                            case "Bold":
                                {
                                    this.FontWeight = FontWeights.Bold;
                                    this.Editor.ParentWindow.tbtnBold.IsChecked = true;
                                    break;
                                }
                            default:
                                {
                                    this.FontWeight = FontWeights.Normal;
                                    this.Editor.ParentWindow.tbtnBold.IsChecked = false;
                                    break;
                                }
                        }
                        break;
                    }
                case "FontSizeLevel":
                    {
                        this.FontSizeLevel = int.Parse(value);
                        break;
                    }
                case "MidLine":
                    {
                        this.Midline = (AssistLine)Enum.Parse(typeof(AssistLine), value);
                        break;
                    }
                //TODO :完成MarkText的其它部分。
            }
        }
    }
}
